package com.yunban.project.template.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yunban.project.template.mapper.TemplateGroupMapper;
import com.yunban.project.template.model.domain.Style;
import com.yunban.project.template.model.domain.TemplateGroup;
import com.yunban.project.template.model.domain.TemplateGroupStyle;
import com.yunban.project.template.model.dto.TemplateGroupReq;
import com.yunban.project.template.model.dto.TemplateGroupSearchReq;
import com.yunban.project.template.model.vo.StyleResp;
import com.yunban.project.template.model.vo.TemplateGroupResp;
import com.yunban.project.template.service.StyleService;
import com.yunban.project.template.service.TemplateCollectService;
import com.yunban.project.template.service.TemplateGroupService;
import com.yunban.project.template.service.TemplateGroupStyleService;
import com.yunban.project.template.utils.IdentityUtils;
import jakarta.annotation.Resource;
import net.lab1024.sa.base.common.domain.PageResult;
import net.lab1024.sa.base.common.domain.RequestUser;
import net.lab1024.sa.base.common.exception.BusinessException;
import net.lab1024.sa.base.common.util.SmartPageUtil;
import net.lab1024.sa.base.common.util.SmartRequestUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class TemplateGroupServiceImpl extends ServiceImpl<TemplateGroupMapper, TemplateGroup> implements TemplateGroupService {

    @Resource
    private TemplateGroupStyleService templateGroupStyleService;

    @Resource
    private StyleService styleService;

    @Resource
    private TemplateCollectService templateCollectService;

    @Override
    public TemplateGroup findById(long id) {
        TemplateGroup group = this.getById(id);
        if (ObjectUtils.isEmpty(group)) {
            throw new BusinessException("模板组不存在");
        }
        return group;
    }

    @Override
    public PageResult<TemplateGroupResp> getTemplateGroupList(TemplateGroupSearchReq req) {
        LambdaQueryWrapper<TemplateGroup> wrapper = new LambdaQueryWrapper<>();
        // 用户ID
        long userId = SmartRequestUtil.getUserId();
        if (StringUtils.hasText(req.getName())) {
            wrapper.like(TemplateGroup::getName, req.getName());
        }
        if (null != req.getHasPublic()) {
            wrapper.eq(TemplateGroup::isHasPublic, req.getHasPublic());
        } else {
            // 如果是客户，那么需要将 hasPublic = true的模板组以及createdBy = 当前用户id的模板组进行展示
            if (IdentityUtils.isCustomer()) {
                wrapper.and(w -> w.eq(TemplateGroup::isHasPublic, true).or().eq(TemplateGroup::getCreatedBy, userId));
            }
        }

        if (!CollectionUtils.isEmpty(req.getStyleIds())) {
            // 根据styleId查询所有的风格组映射
            List<Long> groupIds = this.templateGroupStyleService.findGroupIdByStyleIds(req.getStyleIds());
            // IN 查询
            wrapper.in(TemplateGroup::getId, groupIds);
        }
        Page<TemplateGroup> paged = this.page(SmartPageUtil.convert2PageQuery(req), wrapper);
        PageResult<TemplateGroupResp> templateGroupRespPageResult = SmartPageUtil.convert2PageResult(paged, TemplateGroupResp.class);
        // 获取风格组
        List<TemplateGroupStyle> templateGroupStyles = this.templateGroupStyleService.list();
        // 获取所有的风格
        List<StyleResp> styleList = SmartPageUtil.convert(this.styleService.list(), StyleResp.class);
        Map<Long, StyleResp> styleMap = styleList.stream().collect(Collectors.toMap(StyleResp::getId, Function.identity()));
        // 查询用户的收藏记录
        List<Long> userCollectList = this.templateCollectService.getUserCollectList(userId);
        templateGroupRespPageResult.getList().forEach(items -> {
            for (TemplateGroupStyle templateGroupStyle : templateGroupStyles) {
                if (items.getId() == templateGroupStyle.getGroupId()) {
                    StyleResp style = styleMap.get(templateGroupStyle.getStyleId());
                    if (!ObjectUtils.isEmpty(style)) {
                        items.getStyleList().add(style);
                    }
                }
            }
            items.setCollected(userCollectList.contains(items.getId()));
        });
        return templateGroupRespPageResult;
    }

    void checkRequestParam(List<Long> styleIds) {
        List<Style> styles = this.styleService.listByIds(styleIds);
        if (styles.size() != styleIds.size()) {
            throw new BusinessException("模板风格信息有误~");
        }
    }

    @Override
    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
    public Boolean saveTemplateGroup(TemplateGroupReq req) {
        // 检查参数是否正确
        this.checkRequestParam(req.getStyleIds());
        TemplateGroup group = new TemplateGroup();
        group.setName(req.getName());
        group.setImg(req.getImg());
        group.setHtml(req.getHtml());
        this.save(group);
        // 同步添加模板组风格映射
        this.templateGroupStyleService.batchSave(group.getId(), req.getStyleIds());
        return true;
    }

    @Override
    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
    public Boolean editTemplateGroup(long id, TemplateGroupReq req) {
        TemplateGroup group = this.findById(id);
        // 检查参数是否正确
        this.checkRequestParam(req.getStyleIds());
        group.setName(req.getName());
        group.setImg(req.getImg());
        group.setHtml(req.getHtml());
        this.updateById(group);
        // 组风格先删除、在添加
        this.templateGroupStyleService.removeByGroupId(id);
        this.templateGroupStyleService.batchSave(id, req.getStyleIds());
        return true;
    }

    @Override
    public Boolean removeTemplateGroup(long id) {
        TemplateGroup group = this.findById(id);
        return this.removeById(group);
    }
}
